//@author A0105536L
package Logic;

/**
 * Class DSCommandParser. This class is to analyze input command and return the
 * correct command type
 * 
 * 
 * 
 */
public class DSCommandParser {

	enum COMMAND_TYPE {
		COMMAND_BACKGROUND, COMMAND_ANIMATION, COMMAND_ADD, COMMAND_DELETE, COMMAND_INVALID, COMMAND_UPDATE, COMMAND_DONE, COMMAND_UNDONE, COMMAND_SEARCH, COMMAND_DISPLAY, COMMAND_UNDO, COMMAND_POSTPONE, COMMAND_OVERDUE, COMMAND_EXIT, COMMAND_EXPAND
	};

	/**
	 * This method is to analyze command and return correct command type
	 * 
	 * @param firstCommand
	 *            First word of the user's string
	 * @param secondCommand
	 *            Rest of the user's string
	 * @return Correct command type
	 */
	public static COMMAND_TYPE parseCommand(String firstCommand,
			String secondCommand) {
		if (isAdd(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_ADD;
		} else if (isDelete(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_DELETE;
		} else if (isUpdate(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_UPDATE;
		} else if (isDone(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_DONE;
		} else if (isUndone(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_UNDONE;
		} else if (isSearch(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_SEARCH;
		} else if (isDisplay(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_DISPLAY;
		} else if (isUndo(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_UNDO;
		} else if (isPostpone(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_POSTPONE;
		} else if (isOverdue(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_OVERDUE;
		} else if (isExit(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_EXIT;
		} else if (isAnimation(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_ANIMATION;
		} else if (isExpand(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_EXPAND;
		} else if (isBackground(firstCommand, secondCommand)) {

			return COMMAND_TYPE.COMMAND_BACKGROUND;
		} else {

			return COMMAND_TYPE.COMMAND_INVALID;
		}

	}

	/**
	 * This method is to check whether the input command is the background
	 * command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the background command
	 */
	private static boolean isBackground(String firstCommand,
			String secondCommand) {
		return firstCommand.equalsIgnoreCase("background")
				&& secondCommand.length() == 0;
	}

	/**
	 * This method is to check whether the input command is the animation
	 * command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the animation command
	 */
	private static boolean isAnimation(String firstCommand, String secondCommand) {
		return firstCommand.equalsIgnoreCase("animation")
				&& secondCommand.length() == 0;
	}

	/**
	 * This method is to check whether the input command is the add command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the add command
	 */
	private static boolean isAdd(String firstCommand, String secondCommand) {
		return (firstCommand.equalsIgnoreCase("ADD") || firstCommand
				.equalsIgnoreCase("add")) && secondCommand.length() > 0;
	}

	/**
	 * This method is to check whether the input command is the exit command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the exit command
	 */
	private static boolean isExit(String firstCommand, String secondCommand) {

		return firstCommand.equalsIgnoreCase("exit")
				&& secondCommand.length() == 0;
	}

	/**
	 * This method is to check whether the input command is the overdue command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the overdue command
	 */
	private static boolean isOverdue(String firstCommand, String secondCommand) {

		return firstCommand.equalsIgnoreCase("overdue")
				&& secondCommand.length() == 0;
	}

	/**
	 * This method is to check whether the input command is the delete command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the delete command
	 */
	private static boolean isDelete(String firstCommand, String secondCommand) {

		return (firstCommand.equalsIgnoreCase("delete") || firstCommand
				.equalsIgnoreCase("del"))
				&& secondCommand.length() > 0
				&& isInteger(secondCommand)
				&& Integer.parseInt(secondCommand) > 0;
	}

	/**
	 * This method is to check whether the input command is the update command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the update command
	 */
	private static boolean isUpdate(String firstCommand, String secondCommand) {

		return (firstCommand.equalsIgnoreCase("update") || firstCommand
				.equalsIgnoreCase("upd"))
				&& secondCommand.length() > 1
				&& isInteger(getFirstWord(secondCommand))
				&& Integer.parseInt(getFirstWord(secondCommand)) > 0;
	}

	/**
	 * This method is to check whether the input command is the done command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the done command
	 */
	private static boolean isDone(String firstCommand, String secondCommand) {
		return firstCommand.equalsIgnoreCase("done")
				&& secondCommand.length() == 1 && isInteger(secondCommand);
	}

	/**
	 * This method is to check whether the input command is the undo command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the undo command
	 */
	private static boolean isUndo(String firstCommand, String secondCommand) {

		return firstCommand.equalsIgnoreCase("undo")
				&& secondCommand.length() == 0;
	}

	/**
	 * This method is to check whether the input command is the undone command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the undone command
	 */
	private static boolean isUndone(String firstCommand, String secondCommand) {

		return firstCommand.equalsIgnoreCase("undone")
				&& secondCommand.length() == 1 && isInteger(secondCommand);
	}

	/**
	 * This method is to check whether the input command is the postpone command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the postpone command
	 */
	private static boolean isPostpone(String firstCommand, String secondCommand) {

		return (firstCommand.equalsIgnoreCase("postpone") || firstCommand
				.equalsIgnoreCase("p"))
				&& isInteger(getFirstWord(secondCommand));
	}

	/**
	 * This method is to check whether the input command is the search command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the search command
	 */
	private static boolean isSearch(String firstCommand, String secondCommand) {

		return firstCommand.equalsIgnoreCase("search")
				&& secondCommand.length() > 0;
	}

	/**
	 * This method is to check whether the input command is the expand command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the expand command
	 */
	private static boolean isExpand(String firstCommand, String secondCommand) {

		return (isInteger(firstCommand) && secondCommand.length() == 0)
				|| ((firstCommand.equals("expand") || firstCommand
						.equals("hide")) && secondCommand.length() == 0);
	}

	/**
	 * This method is to check whether the input command is the display command
	 * 
	 * @param firstCommand
	 * @param secondCommand
	 * @return True if the input command is the display command
	 */
	private static boolean isDisplay(String firstCommand, String secondCommand) {

		return firstCommand.equalsIgnoreCase("all")
				&& secondCommand.length() == 0;
	}

	private static boolean isInteger(String integerString) {

		try {
			Integer.parseInt(integerString);
			return true;
		} catch (NumberFormatException nfe) {
			return false;
		}
	}

	private static String getFirstWord(String userCommand) {

		String commandTypeString = userCommand.trim().split("\\s+")[0];
		return commandTypeString;

	}

}